package com.laicunba.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.laicunba.constant.AttributeConstant;
import com.laicunba.dao.GenericQueryDao;
import com.laicunba.pojo.BaseDO;
import com.laicunba.pojo.RemainProfitDO;
import com.laicunba.pojo.UserBankDO;
import com.laicunba.pojo.UserDO;
import com.laicunba.pojo.vo.UserProfileVO;
import com.laicunba.service.AlertService;
import com.laicunba.service.RemainProfitService;
import com.laicunba.service.UserService;
import com.laicunba.service.security.SecurityService;
import com.laicunba.util.AssertUtil;
import com.laicunba.util.MD5Util;

@Service
public class UserServiceImpl extends BaseServiceImpl implements UserService {
	private final static Logger LOG = Logger.getLogger(UserServiceImpl.class);
	@Autowired
	private GenericQueryDao queryDao;
	@Autowired
	private SecurityService securityService;
	@Autowired
	private RemainProfitService remainProfitService;
	@Autowired
	private AlertService alertService;

	@Override
	public UserDO findByMobile(String mobile) {
		return queryDao.selectOne("USER.findByMobile", mobile);
	}

	@Override
	public UserProfileVO getProfile(String userId) {
		return queryDao.selectOne("USER.getProfile", userId);
	}

	@Override
	public List<UserDO> findListByInviteCode(String inviteCode) {
		return queryDao.selectList("USER.findListByInviteCode", inviteCode);
	}

	@Override
	public UserDO findByInviteCode(String inviteCode) {
		return queryDao.selectOne("USER.findByInviteCode", inviteCode);
	}

	@Override
	public UserDO findInviteUser(String userId) {
		return queryDao.selectOne("USER.findInviteUser", userId);
	}

	@Override
	public boolean isNewInvestor(String userId) {
		return (Integer) queryDao.selectOne("USER.countBidTimesHasBankInfo", userId) == 0;
	}

	@Override
	public int countBidTimesHasBankInfo(String userId) {
		return (Integer) queryDao.selectOne("USER.countBidTimesHasBankInfo", userId);
	}

	@Transactional
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public boolean addRemainProfit(String userId, BigDecimal profit) {
		Map map = new HashMap();
		map.put("userId", userId);
		map.put("profit", profit);
		AssertUtil.assertTrue(updateDao.update("USER.addRemainProfit", map) == 1, "ADD_REMAIN_PROFIT_FAIL");
		RemainProfitDO remainProfitDO = new RemainProfitDO();
		remainProfitDO.setAmount(profit);
		remainProfitDO.setSortNum(System.currentTimeMillis());
		remainProfitDO.setUserId(userId);
		AssertUtil.assertTrue(remainProfitService.create(remainProfitDO), "CREATE_REMAIN_PROFIT_FAIL");
		return true;
	}

	@Transactional
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public boolean subtractRemainProfit(String userId, BigDecimal profit) {
		Map map = new HashMap();
		map.put("userId", userId);
		map.put("profit", profit);
		AssertUtil.assertTrue(updateDao.update("USER.subtractRemainProfit", map) == 1, "SUBTRACT_REMAIN_PROFIT_FAIL");
		RemainProfitDO remainProfitDO = new RemainProfitDO();
		remainProfitDO.setAmount(BigDecimal.ZERO.subtract(profit));
		remainProfitDO.setSortNum(System.currentTimeMillis());
		remainProfitDO.setUserId(userId);
		AssertUtil.assertTrue(remainProfitService.create(remainProfitDO), "CREATE_REMAIN_PROFIT_FAIL");
		return true;
	}

	@Transactional
	@Override
	public synchronized boolean create(BaseDO entiry) {
		UserDO userDO = (UserDO) entiry;
		userDO.setRemainProfit(BigDecimal.ZERO);
		UserDO existUserDO = findByMobile(userDO.getMobile());
		AssertUtil.assertTrue(existUserDO == null, "USER_EXIST");
		return super.create(entiry);
	}

	@Override
	public List<UserDO> findByBirthday(String birthday, int limit) {
		Map map = new HashMap();
		map.put("birthday", birthday);
		map.put("limit", limit);
		return queryDao.selectList("USER.findByBirthday", map);
	}

	@Override
	public int count() {
		return queryDao.selectOne("USER.count", null);
	}

	@Override
	public List<Map<String, String>> findListByInviteFrom(String inviteFrom, String openDate) {
		Map<String, String> map = new HashMap<String, String>();
		map.put("inviteFrom", inviteFrom);
		map.put("openDate", openDate);
		return queryDao.selectList("WHOLE_USER_ANALYSIS.userInviteInfo", map);
	}

	@Override
	public boolean isLoginPwdRight(UserDO user, String loginPwdEncrypt) {
		try {
			String loginPwdDecrypt = securityService.decryptWithPrivate(loginPwdEncrypt);
			if (!loginPwdDecrypt.contains("|")) {
				return false;
			}
			String[] pwd = loginPwdDecrypt.split("\\|");
			// if (pwd[1].length()>=13&&(System.currentTimeMillis() -
			// Long.parseLong(pwd[1])) > AttributeConstant.USER_RSA_LIVE) {
			// alertService.info(user.getMobile(),
			// String.format("H5端用户[%s]登录时,加密串失效,服务器时间[%s],加密串时间[%s]",
			// user.getMobile(), System.currentTimeMillis(), pwd[1]));
			// return false;
			// }

			return user.getLoginPwd().equalsIgnoreCase(MD5Util.md5Hex(pwd[0]));
		} catch (Exception e) {
			return false;
		}
	}

	@Override
	public String decryptAndSplitPwd(String encryptLoginPwd) {
		try {
			return securityService.decryptWithPrivate(encryptLoginPwd).split("\\|")[0];
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public boolean update2CurrentAccount(String uid) {
		return updateDao.update("USER.update2CurrentAccount", uid) == 1;
	}

	@Override
	public boolean isUsedCurrentAccount(String hType) {
		return "CURRENT_ACCOUNT".equalsIgnoreCase(hType);
	}

	@Override
	public boolean updateAppInfo(UserDO user) {
		return updateDao.update("USER.updateAppInfo", user) == 1;
	}

	@Override
	public String testDangerous(String uid) {
		Integer diffBindCardCount = (Integer) queryDao.selectOne("USER_DANGEROUS_CHECK.diffBindCardCount", uid);
		if (diffBindCardCount > 1) {
			return "HAS_DIFF_NAME_CARD";
		}
		return null;
	}

	@Override
	public boolean isPidBindByOtherUsr(String pid, String userId) {
		Map map = new HashMap();
		map.put("pid", pid);
		map.put("uid", userId);
		return (Integer) queryDao.selectOne("USER.isPidBindByOtherUsr", map) > 0;
	}

	@Override
	public int count(String beginDate, String endDate) {
		Map map = new HashMap();
		map.put("beginDate", beginDate);
		map.put("endDate", endDate);
		return (Integer) queryDao.selectOne("USER.countByDate", map);
	}

	@Transactional
	@Override
	public boolean updateStatus(String uid, String newStatus, String reson) {
		Map map = new HashMap();
		map.put("uid", uid);
		map.put("newStatus", newStatus);
		map.put("reson", reson);
		AssertUtil.assertTrue(updateDao.update("USER.updateStatus", map) == 1, "");
		return true;
	}

	@Override
	public boolean updateJzhStatus(String uid, String newStatus) {
		Map map = new HashMap();
		map.put("uid", uid);
		map.put("newStatus", newStatus);
		return updateDao.update("USER.updateJzhStatus", map) == 1;
	}

	@Override
	public BigDecimal findBalance(String uid) {
		return this.queryDao.selectOne("USER.findBalance", uid);
	}

	@Override
	public List<UserDO> findByPid(String pid) {
		return queryDao.selectList("USER.findByPid", pid);
	}
}
